package com.wangwenjun.concurrency.chapter14.completablefuture;

import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class UseCompletableFuture1 {

    public static void main(String[] args) {
        test01();
    }


    /**
     * 1. CompletableFuture中的是回调函数比起异步阻塞更优雅
     * 2. CompletableFuture中的线程都是守护线程,程序没了它就没了
     */
    public static void test01(){
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + " start run");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return "ok";
        }).whenComplete((a, b) -> {
            System.out.println(Thread.currentThread().getName() + " over, get result: " + a);
        });


        try {
            String s = future.get(); // 这里同样会阻塞,先whenComplete执行完再get返回
            System.out.println(Thread.currentThread().getName()+" get result: "+s);
            Thread.currentThread().join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *  CompletableFuture.supplyAsync -> thenAccept -> whenComplete
     *  以任务为链,当前任务链的某个节点完成任务了就可以继续往下一个节点执行
     */
    public static void test02(){
      IntStream.range(0, 10).boxed().forEach(i -> CompletableFuture.supplyAsync(UseCompletableFuture1::get).thenAccept(UseCompletableFuture1::display).whenComplete((a, b)-> System.out.println(i+" over "+Thread.currentThread().getName())));
        try {
            Thread.currentThread().join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }


    private static void display(int data){
        int i = ThreadLocalRandom.current().nextInt(20);
        try {
            System.out.println(Thread.currentThread()+" display will sleep "+i);
            TimeUnit.SECONDS.sleep(i);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread()+" display execute "+data);
    }


    private static int get(){
        int i = ThreadLocalRandom.current().nextInt(20);
        try {
            TimeUnit.SECONDS.sleep(i);
            System.out.println(Thread.currentThread()+"work end sleep "+i);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return i;
    }


}
